package com.zbkj.front.controller;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zbkj.common.config.CrmebConfig;
import com.zbkj.common.constants.*;
import com.zbkj.common.exception.CrmebException;
import com.zbkj.common.model.community.CommunityNotes;
import com.zbkj.common.model.communityOrder.CommunityOrder;
import com.zbkj.common.model.communityOrder.NoteTopic;
import com.zbkj.common.model.communityOrder.UserNote;
import com.zbkj.common.model.communityOrder.UserNoteTopic;
import com.zbkj.common.model.merchant.MerchantCategory;
import com.zbkj.common.model.order.Order;
import com.zbkj.common.model.system.SystemUserLevel;
import com.zbkj.common.model.user.User;
import com.zbkj.common.model.user.UserBalanceRecord;
import com.zbkj.common.model.wechat.video.PayComponentDraftProduct;
import com.zbkj.common.page.CommonPage;
import com.zbkj.common.request.*;
import com.zbkj.common.response.*;
import com.zbkj.common.result.CommonResult;
import com.zbkj.common.utils.CrmebDateUtil;
import com.zbkj.common.utils.CrmebUtil;
import com.zbkj.common.utils.RedisUtil;
import com.zbkj.common.vo.PreOrderInfoVo;
import com.zbkj.common.vo.ProCategoryCacheVo;
import com.zbkj.front.service.CommunityFrontService;
import com.zbkj.front.service.FrontProductService;
import com.zbkj.front.service.impl.FrontOrderServiceImpl;
import com.zbkj.service.service.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("api/front/topic")
@Api(tags = "专题控制器") //配合swagger使用
public class TopicFrontController {

    private final Logger logger = LoggerFactory.getLogger(TopicFrontController.class);

    @Autowired
    private CommunityNotesService notesService;


    @Autowired
    private NoteTopicService noteTopicService;

    @Autowired
    private UserNoteTopicService userNoteTopicService;

    @Autowired
    private UserNoteService userNoteService;

    @Autowired
    private UserService userService;

    @Autowired
    private CommunityNotesRelationService communityNotesRelationService;

    @Autowired
    private CommunityOrderService communityOrderService;

    @Autowired
    private FrontProductService productService;

    @Autowired
    private SystemUserLevelService systemUserLevelService;

    @Autowired
    private UserBalanceRecordService userBalanceRecordService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private CrmebConfig crmebConfig;
    @Autowired
    private CommunityFrontService communityFrontService;



    @Autowired
    private RedisUtil redisUtil;

    @ApiOperation(value = "根据专题查询笔记")
    @RequestMapping(value = "/userTopic/{topicId}", method = RequestMethod.GET)
    public CommonResult<HashMap>  getMerchantCacheTree(@PathVariable(value = "topicId") Integer topicId, @ModelAttribute PageParamRequest pageParamRequest) {
        User info = userService.getInfo();
        Page<CommunityNotes> page = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        List<CommunityNotes> list = new ArrayList<>();

        NoteTopic byId = noteTopicService.getById(topicId);
        byId.setNickname(info.getNickname());
        byId.setAvatar(info.getAvatar());
        if (byId.getIsFree()==0){
            LambdaQueryWrapper<CommunityNotes> lqw = Wrappers.lambdaQuery();
            lqw.eq(CommunityNotes::getIsDel, false);
            lqw.eq(CommunityNotes::getTopicId, topicId);
            lqw.orderByDesc(CommunityNotes::getId);
            byId.setIsPay(0);
            list = notesService.list(lqw).stream()
                    .peek(CommunityNotes -> CommunityNotes.setIsPay(0)) // 设置年龄为40
                    .collect(Collectors.toList());

        }else{
            LambdaQueryWrapper<UserNoteTopic> noteTopicLambdaQueryWrapper = Wrappers.lambdaQuery();
            noteTopicLambdaQueryWrapper.eq(UserNoteTopic::getIsDel, false);
            noteTopicLambdaQueryWrapper.eq(UserNoteTopic::getTopicId, topicId);
            noteTopicLambdaQueryWrapper.eq(UserNoteTopic::getUserId, info.getId());
            UserNoteTopic one = userNoteTopicService.getOne(noteTopicLambdaQueryWrapper);
            if (one==null) {
                LambdaQueryWrapper<CommunityNotes> lqw = Wrappers.lambdaQuery();
                lqw.eq(CommunityNotes::getIsDel, false);
                lqw.eq(CommunityNotes::getTopicId, topicId);
                lqw.orderByDesc(CommunityNotes::getId);
                byId.setIsPay(1);
                list = notesService.list(lqw).stream()
                        .peek(CommunityNotes -> CommunityNotes.setIsPay(1)) // 设置年龄为40
                        .collect(Collectors.toList());
            }else{
                LambdaQueryWrapper<CommunityNotes> lqw = Wrappers.lambdaQuery();
                lqw.eq(CommunityNotes::getIsDel, false);
                lqw.eq(CommunityNotes::getTopicId, topicId);
                lqw.orderByDesc(CommunityNotes::getId);
                byId.setIsPay(0);
                list = notesService.list(lqw).stream()
                        .peek(CommunityNotes -> CommunityNotes.setIsPay(0)) // 设置年龄为40
                        .collect(Collectors.toList());
            }
        }
        List<CommunityNoteFrontPageResponse> communityNoteFrontPageResponses = notesListToResponseList(list, info.getId());

        PageInfo<CommunityNoteFrontPageResponse> communityNotesPageInfo = CommonPage.copyPageInfo(page, communityNoteFrontPageResponses);
        HashMap map = new HashMap();
        map.put("noteTopic",byId);
        map.put("notes",communityNotesPageInfo);
        return CommonResult.success(map);
    }

    private List<CommunityNoteFrontPageResponse> notesListToResponseList(List<CommunityNotes> notesList, Integer userId) {
        List<Integer> uidList = notesList.stream().map(CommunityNotes::getUid).distinct().collect(Collectors.toList());
        if (uidList.size()>0) {

                Map<Integer, User> userMap = userService.getUidMapList(uidList);
                return notesList.stream().map(note -> {
                    CommunityNoteFrontPageResponse response = new CommunityNoteFrontPageResponse();
                    response.setId(note.getId());
                    response.setIsPay(note.getIsPay());
                    response.setTopicId(note.getTopicId());
                    response.setTitle(note.getTitle());
                    response.setType(note.getType());
                    response.setCover(note.getCover());
                    response.setViews(note.getViews());
                    response.setAuthorId(note.getUid());
                    response.setAuthorName(userMap.get(note.getUid()).getNickname());
                    response.setAuthorAvatar(userMap.get(note.getUid()).getAvatar());
                    response.setLikeNum(note.getLikeNum());
                    response.setIsPay(note.getIsPay());
                    if (ObjectUtil.isNotNull(userId) && userId > 0) {
                        response.setUserIsLike(communityNotesRelationService.isLikeByUid(note.getId(), userId));
                    }
                    if (userMap.get(note.getUid()).getLevel() > 0) {
                        SystemUserLevel userLevel = systemUserLevelService.getByLevelId(userMap.get(note.getUid()).getLevel());
                        response.setUserLevelIcon(userLevel.getIcon());
                    }
                    if (ObjectUtil.isNotNull(note.getAuditStatus())) {
                        response.setAuditStatus(note.getAuditStatus());
                    }
                    return response;
                }).collect(Collectors.toList());
        }
        return  new ArrayList<CommunityNoteFrontPageResponse>();
    }

    @ApiOperation(value = "生成预订单(包括专题,付费笔记,临时订单)")
    @RequestMapping(value = "/pre/order", method = RequestMethod.POST)
    public CommonResult<OrderNoResponse>  order(@RequestBody @Validated CommunityPreOrderRequest request){
        User user = userService.getInfo();
        CommunityOrder communityOrder = request.getCommunityOrder();
        communityOrder.setUserId(user.getId());
        communityOrder.setUserName(user.getNickname());
        communityOrder.setUserImg(user.getAvatar());
        User byId = userService.getById(communityOrder.getUid());
        if (communityOrder.getTargetType()==0) {
            CommunityNotes communityNotes = notesService.getById(communityOrder.getTargetId());
            communityOrder.setNotes(communityNotes);
            communityOrder.setPayPrice(communityNotes.getPrice());
            communityOrder.setTotalPrice(communityNotes.getPrice());
        }else if(communityOrder.getTargetType()==1){
            NoteTopic topic = noteTopicService.getById(communityOrder.getTargetId());
            communityOrder.setNoteTopic(topic);
            communityOrder.setPayPrice(topic.getPrice());
            communityOrder.setTotalPrice(topic.getPrice());
        }

        communityOrder.setUser(byId);

        String key = user.getId() + CrmebDateUtil.getNowTime().toString() + CrmebUtil.getUuid();

        redisUtil.set(OrderConstants.PRE_ORDER_CACHE_PREFIX + key, JSONObject.toJSONString(communityOrder), OrderConstants.PRE_ORDER_CACHE_TIME, TimeUnit.MINUTES);
        OrderNoResponse response = new OrderNoResponse();
        response.setOrderNo(key);
        response.setOrderType(0);
        response.setPayPrice(communityOrder.getPayPrice());
        logger.info("preOrder response:{}", JSON.toJSONString(response));
        return CommonResult.success(response);
    }

    @ApiOperation(value = "加载预下单(包括专题,付费笔记,临时订单)")
    @RequestMapping(value = "load/pre/{preOrderNo}", method = RequestMethod.GET)
    public CommonResult<CommunityOrder> loadPreOrder(@PathVariable String preOrderNo) {
        UserInfoResponse userInfo = userService.getUserInfo();
        // 通过缓存获取预下单对象
        String key = OrderConstants.PRE_ORDER_CACHE_PREFIX + preOrderNo;
        boolean exists = redisUtil.exists(key);
        if (!exists) {
            throw new CrmebException("预下单订单不存在");
        }
        String orderVoString = redisUtil.get(key);
        CommunityOrder orderInfoVo = JSONObject.parseObject(orderVoString, CommunityOrder.class);
        return CommonResult.success(orderInfoVo);
    }

    @ApiOperation(value = "创建订单")
    @RequestMapping(value = "/create", method = RequestMethod.POST)
    public CommonResult<OrderNoResponse> createOrder(@Validated @RequestBody CreateCommunityRequest orderRequest) {
        User user = userService.getInfo();
        // 通过缓存获取预下单对象
        String key = OrderConstants.PRE_ORDER_CACHE_PREFIX + orderRequest.getOrderNo();
        boolean exists = redisUtil.exists(key);
        if (!exists) {
            throw new CrmebException("预下单订单不存在");
        }
        String orderVoString = redisUtil.get(key).toString();
        CommunityOrder orderInfoVo = JSONObject.parseObject(orderVoString, CommunityOrder.class);
        String orderNo = CrmebUtil.getOrderNo(OrderConstants.ORDER_PREFIX_PLATFORM);
        orderInfoVo.setOrderSn(orderNo);
        orderInfoVo.setCreateTime(CrmebDateUtil.nowDateTime());
        communityOrderService.save(orderInfoVo);
        // 删除缓存订单
        if (redisUtil.exists(key)) {
            redisUtil.delete(key);
        }

        // 加入自动未支付自动取消队列
        redisUtil.lPush(TaskConstants.ORDER_TASK_REDIS_KEY_AUTO_CANCEL_KEY, orderInfoVo.getOrderSn());

        OrderNoResponse response = new OrderNoResponse();
        response.setOrderNo(orderNo);
        response.setPayPrice(orderInfoVo.getPayPrice());

        return CommonResult.success(response);
    }

    @ApiOperation(value = "订单支付")
    @RequestMapping(value = "/payment", method = RequestMethod.POST)
    public CommonResult<OrderPayResultResponse> payment(@RequestBody @Validated OrderPayRequest orderPayRequest) {
        logger.info("订单支付 START orderPayRequest:{}", JSON.toJSONString(orderPayRequest));
        LambdaQueryWrapper<CommunityOrder> lqw = Wrappers.lambdaQuery();
        lqw.eq(CommunityOrder::getIsDel, false);
        lqw.eq(CommunityOrder::getOrderSn, orderPayRequest.getOrderNo());
        CommunityOrder order = communityOrderService.getOne(lqw);
        logger.info("订单支付 当前操作的订单信息:{}", JSON.toJSONString(order));
        if (order.getStatus() == 3) {
            throw new CrmebException("订单已取消");
        }
        if (order.getStatus()==1) {
            throw new CrmebException("订单已支付");
        }

        User user = userService.getInfo();

        // 获取过期时间
        DateTime cancelTime = DateUtil.offset(order.getCreateTime(), DateField.MINUTE, crmebConfig.getOrderCancelTime());
        long between = DateUtil.between(cancelTime, DateUtil.date(), DateUnit.SECOND, false);
        if (between > 0) {
            throw new CrmebException("订单已过期");
        }

        // 余额支付
        if (orderPayRequest.getPayType().equals(PayConstants.PAY_TYPE_YUE)) {
            if (user.getNowMoney().compareTo(order.getPayPrice()) < 0) {
                throw new CrmebException("用户余额不足");
            }
        }

        OrderPayResultResponse response = new OrderPayResultResponse();
        response.setOrderNo(order.getOrderSn());
        response.setPayType("yue");
        response.setPayChannel("yue");
        if (order.getPayPrice().compareTo(BigDecimal.ZERO) <= 0) {
            throw new CrmebException("支付金额不能低于等于0元");
        }
        // 余额支付

        Boolean yueBoolean = yuePay(order, user);
        response.setStatus(yueBoolean);
        logger.info("余额支付 response : {}", JSON.toJSONString(response));


        return CommonResult.success(response);
    }

    /**
     * 余额支付
     *
     * @param order 订单
     * @return Boolean Boolean
     */
    private Boolean yuePay(CommunityOrder order, User user) {
        // 用户余额扣除
        Boolean execute = transactionTemplate.execute(e -> {
            Boolean update = Boolean.TRUE;
            // 订单修改

            order.setStatus(OrderConstants.ORDER_STATUS_WAIT_SHIPPING);
            communityOrderService.updateById(order);
            // 这里只扣除金额，账单记录在task中处理
            if (order.getPayPrice().compareTo(BigDecimal.ZERO) > 0) {
                User byId = userService.getById(user);
                if (byId.getNowMoney().compareTo(order.getPayPrice())<0) {
                    throw new CrmebException("用户金额不能低于订单金额");
                }
                byId.setNowMoney(byId.getNowMoney().subtract(order.getPayPrice()));
                update = userService.updateById(byId);

                if (!update) {
                    logger.error("余额支付，扣除用户余额失败，orderNo = {}", order.getOrderSn());

                    return update;
                }
                // 用户余额记录
                UserBalanceRecord userBalanceRecord = new UserBalanceRecord();
                userBalanceRecord.setUid(user.getId());
                userBalanceRecord.setLinkId(order.getOrderSn());
                userBalanceRecord.setLinkType(BalanceRecordConstants.BALANCE_RECORD_LINK_TYPE_ORDER);
                userBalanceRecord.setType(BalanceRecordConstants.BALANCE_RECORD_TYPE_SUB);
                userBalanceRecord.setAmount(order.getPayPrice());
                userBalanceRecord.setBalance(user.getNowMoney().subtract(order.getPayPrice()));
                userBalanceRecord.setRemark(StrUtil.format(BalanceRecordConstants.BALANCE_RECORD_REMARK_ORDER, order.getPayPrice()));
                userBalanceRecordService.save(userBalanceRecord);
            }
            if( order.getTargetType()==0){
                UserNote userNote = new UserNote();
                userNote.setUserId(user.getId());
                userNote.setNoteId(order.getTargetId());
                userNoteService.save(userNote);
            }else if(order.getTargetType()==1){
                UserNoteTopic userNote = new UserNoteTopic();
                userNote.setUserId(user.getId());
                userNote.setTopicId(order.getTargetId());
                userNoteTopicService.save(userNote);
            }
            return update;
        });
        if (!execute) throw new CrmebException("余额支付订单失败");
        return true;
    }

    @ApiOperation(value = "订单详情")
    @RequestMapping(value = "/detail/{orderNo}", method = RequestMethod.GET)
    public CommonResult<CommunityOrder> orderDetail(@PathVariable String orderNo) {
        LambdaQueryWrapper<CommunityOrder> lqw = Wrappers.lambdaQuery();
        lqw.eq(CommunityOrder::getIsDel, false);
        lqw.eq(CommunityOrder::getOrderSn, orderNo);
        CommunityOrder order = communityOrderService.getOne(lqw);
        return CommonResult.success(order);
    }


    @ApiOperation(value = "创建社区笔记同步商品")
    @RequestMapping(value = "/addNoteProduct", method = RequestMethod.POST)
    public CommonResult<Object> createNote(@RequestBody @Validated CommunityNoteSaveRequest request) {
        Integer integer = productService.saveTwo(request.getProductAddRequest());
        if (request.getProIds()==null || request.getProIds().equals("")) {
            request.setProIds(integer.toString());
        }else{
            request.setProIds(request.getProIds()+","+integer.toString());
        }

        communityFrontService.createNote(request);
        return CommonResult.success();
    }

    @ApiOperation(value = "创建用户专题")
    @RequestMapping(value = "/addNoteTopic", method = RequestMethod.POST)
    public CommonResult<Object> createNote(@RequestBody @Validated NoteTopic request) {
        Integer userId = userService.getUserIdException();
        request.setIsAdmin(1);
        request.setUid(userId);
        noteTopicService.save(request);
        return CommonResult.success();
    }

    @ApiOperation(value = "修改笔记浏览量")
    @RequestMapping(value = "/updateNoteCount/{id}", method = RequestMethod.GET)
    public CommonResult<Object> updateNoteCount(@PathVariable Integer id) {
        CommunityNotes byId = notesService.getById(id);
        byId.setViews(byId.getViews().intValue()+1);
        notesService.saveOrUpdate(byId);
        return CommonResult.success();
    }

    @ApiOperation(value = "用户专题下拉框")
    @RequestMapping(value = "/getUserNoteTopic", method = RequestMethod.GET)
    public CommonResult<List<NoteTopic>> getUserNoteTopic() {
        Integer userId = userService.getUserIdException();
        LambdaQueryWrapper<NoteTopic> lqw = Wrappers.lambdaQuery();
        lqw.eq(NoteTopic::getIsDel, false);
        lqw.eq(NoteTopic::getUid, userId);
        List<NoteTopic> list = noteTopicService.list(lqw);
        return CommonResult.success(list);
    }
}
